#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

#define Size 10

// 初始化函数
void InitBoard(char (*Board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            Board[i][j] = '-';
        }
    }
}

// 打印棋盘
void PrintBoard(char (*Board)[Size])
{
    printf("   ");
    for (int i = 0; i < Size; i++)
    {
        printf("%3d", i + 1);
    }
    printf("\n");

    for (int i = 0; i < Size; i++)
    {
        printf("%3d", i + 1);
        for (int j = 0; j < Size; j++)
        {
            printf("%3c", Board[i][j]);
        }
        printf("\n");
    }
}

// 下棋
bool MakeMove(char (*Board)[Size], int row, int column, char player)
{
    // 非法位置
    if (row < 0 || row >= Size || column < 0 || column >= Size)
    {
        printf("非法的下棋位置，请重新输入！\n");
        return false;
    }
    // 该位置已经有棋子
    if (Board[row][column] != '-')
    {
        printf("该位置已经有棋子，请重新输入！\n");
        return false;
    }

    Board[row][column] = player;
    return true;
}

// 判断位置是否合法
bool IsValidPlace(int row, int column)
{
    if (row < 0 || row >= Size || column < 0 || column >= Size)
        return false;
    return true;
}

// 判胜
bool CheckIsWin(char (*Board)[Size], int row, int column, char player)
{
    int direction[4][2] =
        {
            {1, 0},
            {1, 1},
            {0, 1},
            {-1, 1}};

    // 遍历4个方向，数棋子数量
    for (int i = 0; i < 4; i++)
    {
        int count = 1;
        // 下一颗棋子的位置
        int dx = row + direction[i][0];
        int dy = column + direction[i][1];
        while (IsValidPlace(dx, dy) && Board[dx][dy] == player)
        {
            count++;
            if (count >= 5)
                return true;
            dx = dx + direction[i][0];
            dy = dy + direction[i][1];
        }

        // 反方向继续找
        dx = row - direction[i][0];
        dy = column - direction[i][1];
        while (IsValidPlace(dx, dy) && Board[dx][dy] == player)
        {
            count++;
            if (count >= 5)
                return true;
            dx = dx - direction[i][0];
            dy = dy - direction[i][1];
        }
    }
    return false;
}

// 判平
bool CheckIsDraw(char (*Board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '-')
                return false;
        }
    }
    return true;
}

bool AIMakeMove(char (*Board)[Size], char player, char ai, int PlayerRow, int PlayerColumn)
{
    // 优先取胜策略
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '-')
            {
                Board[i][j] = ai;
                if (CheckIsWin(Board, i, j, ai) == true)
                {
                    return true;
                }
                Board[i][j] = '-';
            }
        }
    }

    // 组织对手策略
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '-')
            {
                Board[i][j] = player;
                if (CheckIsWin(Board, i, j, player) == true)
                {
                    Board[i][j] = ai;
                    return true;
                }
                Board[i][j] = '-';
            }
        }
    }

    // 下在玩家周围策略
    int direction[8][2] =
        {
            {1, 0},
            {-1, 0},
            {0, 1},
            {0, -1},
            {1, 1},
            {1, -1},
            {-1, 1},
            {-1, -1}};

    // 随机数的产生由随机种子决定
    // 随机种子不变，随机数就不会变
    // 以当前时间作为随机种子

    while (1)
    {
        srand(time(NULL));
        int i = rand() % 8;
        int dx = PlayerRow + direction[i][0];
        int dy = PlayerColumn + direction[i][1];
        if (IsValidPlace(dx, dy) && Board[dx][dy] == '-')
        {
            Board[dx][dy] = ai;
            return true;
        }
    }
    return false;
}

int main()
{
    char Board[Size][Size] = {0};
    InitBoard(Board);
    char player = 'X';
    int row = 0, column = 0;
    while (1)
    {
        PrintBoard(Board);

        printf("请|%c|选手下棋:", player);
        // 玩家下棋
        if (player == 'X')
        {
            // 阻塞性函数：让程序进入等待状态，直到条件满足继续执行
            scanf("%d %d", &row, &column);

            if (MakeMove(Board, row - 1, column - 1, player) == false)
            {
                continue;
            }
        }
        // 电脑下棋
        else
        {
            printf("AI正在下棋...\n");
            if (AIMakeMove(Board, 'X', 'O', row - 1, column - 1) == false)
            {
                continue;
            }
        }

        if (CheckIsWin(Board, row - 1, column - 1, player) == true)
        {
            PrintBoard(Board);
            printf("恭喜|%c|选手获胜\n", player);
            break;
        }

        if (CheckIsDraw(Board) == true)
        {
            PrintBoard(Board);
            printf("平局!\n");
            break;
        }
        player = (player == 'X' ? 'O' : 'X');
    }
    return 0;
}